﻿using SG;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
 * 音效组，播放的时候会自动找一个空闲的AudioSource来使用
 */
public class AudioGroup : MonoBehaviour
{

    bool m_bMute = false;
    float m_fVolume = 1;
    float t_FadeIn = 2;
    float t_FadeOut = 2;
    AudioManager.eSoundType m_eAudioType;
    List<AudioSource> m_AudioList = new List<AudioSource>();
    AudioSource m_OneShot;
    void Start()
    {
        ////EventMgr.Instance().AddListener((int)GameEventDef.GE_CC_SOUND_MODIFY, OnSoundModify);
        //var audios = GetComponents<AudioSource>();
        //foreach (var item in audios)
        //{
        //    m_AudioList.Add(item);
        //}
    }
    private void OnDestroy()
    {
        //EventMgr.Instance().RemoveListener((int)GameEventDef.GE_CC_SOUND_MODIFY, OnSoundModify);
    }
    public void DoInit(AudioManager.eSoundType type, int nNum = 0)
    {
        m_eAudioType = type;
        if (nNum > 0)
        {
            for (int i = m_AudioList.Count; i < nNum; ++i)
            {
                var audio = AddAudioSource(gameObject);
                m_AudioList.Add(audio);
            }
        }
        FreshAudioData();
        m_OneShot = AddAudioSource(gameObject);
    }
    void FreshAudioData()
    {
        m_fVolume = AudioManager.Instance().GetVolume(m_eAudioType);
        foreach (var item in m_AudioList)
        {
            item.mute = m_bMute;
            item.volume = m_fVolume;
        }
    }


    public void SetAudioMute(bool bMute)
    {
        foreach (var item in m_AudioList)
        {
            item.mute = m_bMute;

        }
    }
    public void SetAudioVolume(float fVolume)
    {
        m_fVolume = fVolume;
        foreach (var item in m_AudioList)
        {
            item.volume = m_fVolume;
        }
    }
    int GetFreeSourceOnly(ref AudioSource audio, bool bGrown, AudioClip clip = null)
    {
        if (m_AudioList.Count == 0)
        {
            audio = AddAudioSource(gameObject);
            m_AudioList.Add(audio);
        }
        audio = m_AudioList[0];
        return 0;
    }
    int GetFreeSource(ref AudioSource audio, bool bGrown, AudioClip clip = null)
    {
        if (bGrown)
        {
            if (clip != null)
            {
                for (int i = 0; i < m_AudioList.Count; ++i)
                {
                    // 如果已经有一个名字一样的正在播放了，就返回
                    if (m_AudioList[i] != null)
                        if (m_AudioList[i].clip.name == (clip.name + "(Clone)"))
                            if (m_AudioList[i].isPlaying)
                            {
                                LogMgr.Instance().LogWarning("{0}被忽略掉了", m_AudioList[i].clip.name);
                                return -1;
                            }
                            else
                            {
                                audio = m_AudioList[i];
                                return i;
                            }

                }
            }
            //for (int i = 0; i < m_AudioList.Count; ++i)
            //{
            //    if (m_AudioList[i] != null && !m_AudioList[i].isPlaying)
            //    {
            //        audio = m_AudioList[i];
            //        return i;
            //    }
            //}
        }
        else
        {
            if (m_eAudioType == AudioManager.eSoundType.BGM)
            {
                StopAllCoroutines();
            }
            if (m_AudioList.Count >= 1)
            {
                audio = m_AudioList[0];
                return 0;
            }
        }
        audio = AddAudioSource(gameObject);
        m_AudioList.Add(audio);
        return m_AudioList.Count - 1;

    }

    public bool IsPlaying(int nIndex)
    {
        if (m_AudioList.Count < nIndex || nIndex < 0)
        {
            return false;
        }

        if (m_AudioList[nIndex].clip != null && m_AudioList[nIndex].isPlaying)
        {
            return true;
        }
        return false;
    }

    public float GetClipTime(int nIndex)
    {
        if (m_AudioList.Count < nIndex || nIndex < 0)
        {
            return 0;
        }

        if (m_AudioList[nIndex].clip != null)
        {
            return m_AudioList[nIndex].clip.length;
        }
        return 0;
    }
    public void PlayBGM(string sFile, string lFile)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSource(ref audio, false);
        StartCoroutine(DoPlayBGM(audio, sFile, lFile));
    }
    IEnumerator DoPlayBGM(AudioSource audio, string sFile, string lFile)
    {
        AudioClip a = ObjectMgr.Instance().CreateAudioClip(sFile);
        AudioClip b = ObjectMgr.Instance().CreateAudioClip(lFile);
        audio.clip = a;
        audio.loop = false;
        audio.Play();
        yield return new WaitForSecondsRealtime(a.length);
        audio.clip = b;
        audio.loop = true;
        if (!aPause)
        {
            audio.Play();
        }
        else
        {
            audio.Pause();
        }
        yield return null;
    }
    public void PlayClip(AudioClip clip)
    {
        XKLog.Log("播放Clip");
        AudioSource audio = null;
        GetFreeSource(ref audio, true);
        if (clip != null)
        {
            audio.clip = clip;
            audio.loop = false;
            audio.Play();
        }
    }

    public int PlayAudio(AudioClip clip, bool bLoop = false, bool bGrown = true)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSource(ref audio, bGrown, clip);
        if (nIndex < 0)
            return nIndex;
        if (audio != null)
        {
            audio.clip = ObjectMgr.Instance().CreateAudioClip(clip);
            audio.loop = bLoop;
            audio.Play();
        }
        return nIndex;
    }
    public int PlayAudioOneShot(AudioClip clip, float fscale)
    {
        m_OneShot.PlayOneShot(ObjectPoolMgr.Instance().GetFreeAudioClipFromPool(clip), m_fVolume * fscale);
        return -1;
    }
    public int PlayAudioOnly(AudioClip clip, float fscale, bool bBreak)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSourceOnly(ref audio, true, clip);
        if (audio != null)
        {
            if (audio.isPlaying)
            {
                if (bBreak)
                    audio.Stop();
                else
                    return nIndex;
            }
            audio.clip = ObjectMgr.Instance().CreateAudioClip(clip);
            audio.loop = false;
            audio.volume = m_fVolume * fscale;
            audio.Play();
        }
        return nIndex;
    }
    public int PlayAudio(AudioClip clip, float fscale)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSource(ref audio, true, clip);
        if (nIndex < 0)
            return nIndex;
        if (audio != null)
        {
            audio.clip = ObjectMgr.Instance().CreateAudioClip(clip);
            audio.loop = false;
            audio.volume = m_fVolume * fscale;
            audio.Play();
        }
        return nIndex;
    }
    public int PlayAudio(string strName, bool bLoop = false, bool bGrown = true)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSource(ref audio, bGrown);
        if (audio != null)
        {
            audio.clip = ObjectMgr.Instance().CreateAudioClip(strName);
            audio.loop = bLoop;
            audio.Play();
        }
        return nIndex;
    }
    public int PlayAudio(string strName, float fscale)
    {
        AudioSource audio = null;
        int nIndex = GetFreeSource(ref audio, true);
        if (audio != null)
        {
            audio.clip = ObjectMgr.Instance().CreateAudioClip(strName);
            audio.loop = false;
            audio.volume = m_fVolume * fscale;
            audio.Play();
        }
        return nIndex;
    }
    public void PlayAudio(int nIndex, string strName, bool bLoop = false)
    {
        var item = m_AudioList[nIndex];
        if (item != null)
        {
            item.loop = bLoop;
            item.clip = ObjectMgr.Instance().CreateAudioClip(strName);
            item.playOnAwake = true;
            item.volume = m_fVolume;
            item.Play();
        }
    }

    int m_nCurIndex = -1;
    string m_strDelayFile = "";
    bool m_bLoop;

    public void PlayAudioDelay(int nIndex, string strName, bool bLoop, float fDelay)
    {
        StopAllCoroutines();
        if (IsPlaying(nIndex))
        {
            StartCoroutine(DoPlayBGMFadeOut(nIndex, strName, bLoop));
        }
        else
        {
            PlayAudio(nIndex, strName, bLoop);
        }

    }

    IEnumerator DoPlayBGMFadeOut(int nIndex, string strName, bool bLoop)
    {
        var audioSource = m_AudioList[nIndex];
        float durTime = 0;
        while (audioSource.volume > 0)
        {
            audioSource.volume = Mathf.Lerp(m_fVolume, 0, durTime / (t_FadeOut * m_fVolume));
            durTime += Time.deltaTime;
            yield return null;
        }
        durTime = 0;
        audioSource.loop = bLoop;
        audioSource.clip = ObjectMgr.Instance().CreateAudioClip(strName);
        audioSource.playOnAwake = true;
        audioSource.Play();
        while (audioSource.volume < m_fVolume)
        {
            audioSource.volume = Mathf.Lerp(0, m_fVolume, durTime / (t_FadeIn * m_fVolume));
            durTime += Time.deltaTime;
            yield return null;
        }
    }
    public void FreshVolume(int nIndex, float volume)
    {
        if (m_AudioList.Count < nIndex || nIndex < 0)
        {
            return;
        }
        var item = m_AudioList[nIndex];
        if (item != null)
        {
            item.volume = volume;
        }
    }
    public void PlayAudio(int nIndex)
    {
        if (m_AudioList.Count < nIndex || nIndex < 0)
        {
            return;
        }
        var item = m_AudioList[nIndex];
        if (item != null)
        {
            item.Play();
        }
    }
    public void StopAudio(int nIndex)
    {
        if (nIndex >= m_AudioList.Count || nIndex < 0)
            return;
        var item = m_AudioList[nIndex];
        if (item != null)
            item.Stop();
    }

    public void PauseAudio(int nIndex, bool isPause = true)
    {
        if (m_AudioList.Count >= nIndex || nIndex < 0)
        {
            return;
        }
        var item = m_AudioList[nIndex];
        if (item != null)
        {
            if (isPause)
            {
                if (item.isPlaying)
                {
                    item.Pause();
                }
            }
            else
            {
                if (!item.isPlaying)
                {
                    item.UnPause();
                }
            }
        }
    }


    bool aPause = false;
    public void PauseAllAudio(bool isPause = true)
    {
        if (m_AudioList.Count < 1)
        {
            return;
        }
        foreach (var item in m_AudioList)
        {
            if (item != null)
            {
                if (isPause)
                {
                    if (item.isPlaying)
                    {
                        item.Pause();
                    }
                }
                else
                {
                    if (!item.isPlaying)
                    {
                        item.UnPause();
                    }
                }
            }

        }
        aPause = isPause;
    }

    public void StopAllAudio()
    {
        if (m_AudioList.Count < 1)
        {
            return;
        }
        foreach (var item in m_AudioList)
        {
            if (item != null)
            {
                item.Stop();
                item.clip = null;
            }

        }
        StopAllCoroutines();
    }

    private AudioSource AddAudioSource(GameObject go)
    {
        AudioSource audioSource = go.AddComponent<AudioSource>();
        audioSource.Stop();
        audioSource.playOnAwake = false;
        audioSource.rolloffMode = AudioRolloffMode.Linear;
        audioSource.loop = false;
        audioSource.mute = m_bMute;
        audioSource.minDistance = 0;
        audioSource.maxDistance = 20;
        audioSource.spatialBlend = 0.0f;

        return audioSource;
    }

    public void To2D()
    {
        foreach (var audioSource in m_AudioList)
        {
            audioSource.spatialBlend = 0.0f;
        }
    }

    public void To3D()
    {
        foreach (var audioSource in m_AudioList)
        {
            audioSource.spatialBlend = 1.0f;
        }
    }
}
